<template>
  <div class="xauto">
    <div style="display: flex;width: 100%;" v-if="!props.disabled">
      <tiny-input
          ref="inputRef"
          v-model="model"
          :clearable="props.clearable"
          autocomplete="off"
          :size="size"
          :placeholder="props.placeholder"
          :disabled="disabled"
          @focus.stop="focused"
          @blur.stop="blured"
          @input.stop="changeVal"
          @clear="clear"
          @keydown.stop="keydown"
      />
      <div title="弹出选择更多" v-if="showMore" style="padding-top: 5px;cursor: pointer;" >
        <TinyIconMore @click="clickMore" />
      </div>
    </div>
    <div class="readonly"  v-else>
      <div >{{model}}</div>
    </div>
    <ul ref="wrapperRef" class="dropdown" :style="{height:wrapperHeight+'px'}" v-if="showDropPanel">
      <li
          v-for="(item, index) in listRemote"
          :key="index"
          :style="{height:itemHeight+'px',lineHeight:itemHeight+'px'}"
          @mousedown.prevent="handleSelect(item,index)"
          :class="[currentIndex===index?'active':'']"
      >
        <span>{{ item.ext?item.ext:'' }} {{item[labelKey]}} </span>
        <span style="padding-left: 10px; color: orange;font-size: 13px;" v-if="item.suffix">
            {{ item.suffix?item.suffix:'' }}
        </span>
      </li>
      <li v-if="addItem"
          style="background-color: #656D78;height: 30px;line-height: 30px;text-align: center;color: white;margin-top: 20px;"
          @mousedown.prevent="add">新增</li>
    </ul>
    <input v-model="id" type="hidden" />
  </div>
</template>

<script setup>
import {IconMore, IconClose,} from '@opentiny/vue-icon'
import {TinyInput} from "@opentiny/vue";
import {ref, nextTick,computed} from 'vue'
import tool from "@/utils/tool";
const props = defineProps({
  cat: {type: String, default: ''},
  valueKey: {type: String, default: 'id'},
  labelKey: {type: String, default: 'name'},
  invId: {type: [Number, String], default: ''},
  buId: {type: [Number, String], default: ''},
  unit: {type: [Number, String], default: ''},
  transType: {type: [Number, String], default: ''},
  qty: {type: [Number, String], default: ''},
  list: {
    type: Array, default: () => {
      return []
    }
  },
  width: {type: [String, Number], default: ''},
  url: {type: [String, Number], default: 'common/dropdown'},
  size: {type: String, default: 'small'},
  searchKey: {type: String, default: ''},
  inject: {type: Boolean, default: false}, // 点击清除后是否重新聚集
  addItem: {type: Boolean, default: false}, // 点击清除后是否重新聚集
  clearToFocus: {type: Boolean, default: false}, // 点击清除后是否重新聚集
  showMore: {type: Boolean, default: false},
  strict: {type: Boolean, default: false}, // blur后，如果名称与id不对应，自动变更 名称
  disabled: {type: Boolean, default: false},
  clearable: {type: Boolean, default: true}, // 是否有清除按钮
  canEdit: {type: Boolean, default: false}, // 有修改
  isGrid: {type: Boolean, default: false}, // 下拉 表格
  focusOpen: {type: Boolean, default: true}, // focus自动打开
  readonly: {type: Boolean, default: false}, // 必填
  required: {type: Boolean, default: false}, // 必填
  pinYin: {type: Boolean, default: false}, // 拼音
  border: {type: Boolean, default: true}, // 禁用
  placeholder: {type: String, default: ''}, // 取数据cat分类
  showDropList: {type: Boolean, default: false}, // 不管有没有数据，显示全部下拉
})
const emit = defineEmits(['change', 'enter', 'Esc', 'down', 'up', 'left', 'right', 'clickMore', 'doEdit', 'itemAdd'])
const TinyIconMore = IconMore()
const id = defineModel('id')
const model = defineModel()
const showDropPanel = ref(false) // 显示下拉框面板
let listRemote = ref([]) // 远程数据列表
const wrapperHeight = 280; // 容器可视高度
const scrollHeight = ref(0);
const itemHeight = 30; // 条目高度
const wrapperRef = ref()
const inputRef = ref()
const currentIndex = ref(-1)
const fApi = ref({})
// 通过api设置的数据列表
const apiSetList = ref([])
const remoteMethod = (queryStr) => {
  const query = tool.xe.trim(queryStr)
  listRemote.value = []
  if (props.list.length > 0) {
    let arr = []
    for (let i = 0; i < props.list.length; i++) {
      if(props.list[i].name.indexOf(query) !== -1) {
        arr.push(props.list[i])
      }
    }
    listRemote.value = arr
    showDropPanel.value = true
  }
  else if (props.cat) {
    tool.post(props.url, {
      cat: props.cat,
      keyWord: query,
      invId: props.invId,
      buId: props.buId,
      unit: props.unit,
      transType: props.transType,
      qty: props.qty,
    }).then((ret) => {
      if (ret.stat) {
        listRemote.value = ret.data
        showDropPanel.value = true
        setTimeout(() => {
          scrollHeight.value = wrapperRef.value?wrapperRef.value.scrollHeight:null
        }, 5)
      }
    })
  }
  else if (apiSetList.value.length > 0) {
    let arr = []
    for (let i = 0; i < apiSetList.value.length; i++) {
      if(apiSetList.value[i].name.indexOf(query) !== -1) {
        arr.push(apiSetList.value[i])
      }
    }
    listRemote.value = arr
    showDropPanel.value = true
  }
}
const add = () => {
  emit('itemAdd')
  showDropPanel.value = false
}
const focused = () => {
  currentIndex.value = -1
  if (props.showDropList) {
    remoteMethod(model.value)
  }
  else {
    if (!model.value) {
      remoteMethod(model.value)
    }
  }
}
const blured = () => {
  // blurToSetVal()
  showDropPanel.value = false
}
const blurToSetVal = () => {
  let ret = tool.xe.trim(model.value)
  if (ret === '') {
    id.value = 0
    model.value = ''
  }
  else {
    if (props.list.length > 0) {
      if (id.value) {
        props.list.map((row) => {
          if (row.id === id.value) {
            model.value = tool.xe.trim(row[props.labelKey])
          }
        })
      }
    }
    else {
      if (listRemote.value.length > 0) {
        if (id.value) {
          listRemote.value.map((row) => {
            if (row.id === id.value) {
              model.value = tool.xe.trim(row[props.labelKey])
            }
          })
        }
      }
      else {
        if(id.value) {
          id.value = 0
          model.value = ''
        }
      }
    }
  }
}
const clear = () => {
  id.value = null
  model.value = ''
  currentIndex.value = -1
  setTimeout(() => {
    inputRef.value.blur()
  }, 1)
  if(props.clearToFocus) {
    setTimeout(() => {
      inputRef.value.focus()
    }, 5)
  }
  emitChange()
  // showDropPanel.value = false
}
const changeVal = (values) => {
  const keyWord = values === '' ? '' : tool.xe.trim(values.target.value)
  remoteMethod(keyWord)
}
const handleSelect = (item, index) => {
  id.value = item[props.valueKey]
  model.value = item[props.labelKey]
  currentIndex.value = index
  emitChange()
  setTimeout(() => {
    showDropPanel.value = false
  }, 10)
}
const emitEnter = () => {
  nextTick(() => {
    let item = null
    if (id.value) {
      if (props.list.length > 0) {
        for (let i = 0; i < props.list.length; i++) {
          if (props.list[i][props.valueKey] === id.value) {
            item = props.list[i]
            break
          }
        }
      }
      if (listRemote.value.length > 0) {
        for (let i = 0; i < listRemote.value.length; i++) {
          if (listRemote.value[i][props.valueKey] === id.value) {
            item = listRemote.value[i]
            break
          }
        }
      }
    }
    doEmit('enter', item)
  })
}
const emitChange = () => {
  nextTick(() => {
    let item = null
    if (id.value) {
      if (props.list.length > 0) {
        for (let i = 0; i < props.list.length; i++) {
          if (props.list[i][props.valueKey] === id.value) {
            item = props.list[i]
            break
          }
        }
      }
      if (listRemote.value.length > 0) {
        for (let i = 0; i < listRemote.value.length; i++) {
          if (listRemote.value[i][props.valueKey] === id.value) {
            item = listRemote.value[i]
            break
          }
        }
      }
    }
    doEmit('change', item)
  })
}
const keydown = (e) => {
  let key = e.key;
  let start = e.target.selectionStart; // 光标位置
  e.stopImmediatePropagation()
  if(key === 'Enter') {
    if (showDropPanel.value) {
      if (currentIndex.value > -1) {
        if (props.list.length > 0) {
          let item = props.list[currentIndex.value]
          id.value = item[props.valueKey]
          model.value = item[props.labelKey]
          emitChange()
          showDropPanel.value = false
        } else {
          let item = listRemote.value[currentIndex.value]
          id.value = item[props.valueKey]
          model.value = item[props.labelKey]
          emitChange()
          showDropPanel.value = false
        }
      }
      if(!props.required) emitEnter()

    }
    else {
      emitEnter()
    }
  }
  else if (key === 'ArrowLeft') {
    if (start === 0) {
      setTimeout(() => {
        emit('left');
      }, 5)
    }
  }
  else if (key === 'ArrowRight') {
    if (start === (model.value ? tool.xe.toString(model.value).length : 0)) {
      setTimeout(() => {
        emit('right');
      }, 5)
    }
  }
  else if (key === 'ArrowDown') {
    if (showDropPanel.value) {
      if (currentIndex.value === listRemote.value.length - 1) {
        currentIndex.value = 0
      } else {
        currentIndex.value++
      }
      const clientHeight = wrapperRef.value.clientHeight // - (wrapperRef.value.clientHeight - itemHeight) / 2;
      const hasits = Math.floor(clientHeight/itemHeight)
      if (currentIndex.value >= hasits) {
        wrapperRef.value.scrollTop =  Math.floor(currentIndex.value * itemHeight/clientHeight) * clientHeight
      }
      if (currentIndex.value === 0) {
        wrapperRef.value.scrollTop = 0
      }
      return
    }
    setTimeout(() => {
      emit('down');
    }, 5)
  }
  else if (key === 'ArrowUp') {
    if (showDropPanel.value) {
      if (currentIndex.value === 0) {
        currentIndex.value = listRemote.value.length - 1
      } else {
        currentIndex.value--
      }
      wrapperRef.value.scrollTop = currentIndex.value * itemHeight;
      return
    }
    setTimeout(() => {
      emit('up');
    }, 5)
  }
  else if (key === 'Escape') {
    showDropPanel.value = false
    setTimeout(() => {
      emit('Esc');
    }, 5)
  }
  else {
    if(e.ctrlKey && key === 's') {
      e.preventDefault()
      inputRef.value.blur()
      tool.suc('再按一次确认')
    }
    if(['F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12'].indexOf(key) !== -1) {
      inputRef.value.blur()
      e.preventDefault()
      tool.suc('再按一次确认')
    }
  }
}
const clickMore = () => {
  doEmit('clickMore')
}

const focus = () => {
  inputRef.value && inputRef.value.focus()
}
const doEmit = (event, val = null) => {
  setTimeout(() => {
    if(props.inject) {
      emit(event, fApi.value, val);
    }
    else {
      emit(event, val);
    }
  }, 1)
}

const doEdit = () => {
  if (props.canEdit) {
    doEmit('doEdit')
  }
}
const setApi = (api) => {
  fApi.value = api
}
const setList = (list) => {
  apiSetList.value = list
}
defineExpose({focus, setApi, setList})

</script>

<style lang="scss" scoped>

.xauto {
  .dropdown {
    box-sizing: border-box;
    background-color: white;
    position: absolute;
    z-index: 99999999999999999;
    overflow: auto;
    min-width: 200px;
    border: 1px solid rgba(0, 0, 0, 0.1);

    li {
      box-sizing: border-box;
      padding: 0 5px;
      white-space: nowrap;
      text-align: left;
      &.active {
        background-color: rgba(0, 0, 0, 0.1);
      }

      &:hover {
        cursor: pointer;
        background-color: rgba(0, 0, 0, 0.1);
      }
    }
  }

  .readonly {
    display: flex;
    border-bottom: 1px solid rgba(0,0,0,0.2);
    height: 28px;
    line-height: 28px;
    color: #2b85e4;
    .edit {
      width: 50px;
      color: #1e9fff;
      &:hover {
        cursor: pointer;
        color: dodgerblue;
      }
    }

  }
}
</style>
